package tools;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import model.Node;
import model.Point;
import model.Segment;
import model.Trapezoid;
import model.TrapezoidPolygon;
import engine.Utils;

public class ResultHolder {
    public ArrayList<Trapezoid> trap; 
    String newline;
    Trapezoid trapezoid;
    Point upperleft;
    Point upperright;
    Point lowerleft;
    Point lowerright;
    String foundcolour = "red";
    String mapcolour = "green";
    String boardercolour = "black";
    String basesegments = "blue";
    String test = "orange";
    List<Point> upperPoints;
    List<Point> lowerPoints;
    List<Segment> baseSegments;
    IOManager iom;
    public Point lookout;
    public int nrOfStates;
    public int minX;
    public int maxX;
    
    public ResultHolder(IOManager manager){
        newline = "\n";
        trap = new ArrayList<Trapezoid>();
        upperPoints = new LinkedList<Point>();
        lowerPoints = new LinkedList<Point>();
        baseSegments = new LinkedList<Segment>();
        iom = manager;
        nrOfStates = 0;
    }

    public void addBaseSegment(Segment s){
    	baseSegments.add(new Segment(s.left, s.right, basesegments));
    }
    
    public void setTrapezoid(Trapezoid t){
    	trapezoid = t;
    }

    public Trapezoid getTrapezoid(){
    	return trapezoid;
    }
  
    
    public List<Point> getResultPoints(){
    	List<Point> result = new LinkedList<Point>();
    	
    	TrapezoidPolygon wynik = Utils.trapezoidToPolygon(trapezoid);
    	
    	for (int i=0; i<4; i++){
    		Point p1 = new Point(wynik.x[i], wynik.y[i], foundcolour, "found"+i);
    		result.add(p1);
    	}
    	return result;
    }
    
    public List<Segment> getResultSegments(){
    	List<Segment> result = new LinkedList<Segment>();
    	
    	List<Point> punkty = new LinkedList<Point>();
    	
    	TrapezoidPolygon wynik = Utils.trapezoidToPolygon(trapezoid);
    	
    	for (int i=0; i<4; i++){
    		Point p1 = new Point(wynik.x[i], wynik.y[i], foundcolour, "found"+i);
    		punkty.add(p1);
    	}
    	
    	Segment s1 = new Segment(punkty.get(0),punkty.get(1),foundcolour);
    	Segment s2 = new Segment(punkty.get(2),punkty.get(3),foundcolour);
    	Segment s3 = new Segment(punkty.get(0),punkty.get(3),foundcolour);
    	Segment s4 = new Segment(punkty.get(1),punkty.get(2),foundcolour);
    	
    	result.add(s1);
    	result.add(s2);
    	result.add(s3);
    	result.add(s4);
    	
    	return result;
    	
    }
    
    public List<Point> getTrapezoidalPoints(){   	
    	List<Point> result = new LinkedList<Point>();
    	Point ul, ll, ur, lr;
    	int counter = 0;
    	for (Trapezoid t : trap){  
    		counter++;
	    	if (t.left == t.top.left)
				ul = new Point(t.left.x, t.left.y, mapcolour, "ul" + counter);
	    	else
	    		ul = new Point(t.left.x, t.left.up, mapcolour, "ul" + counter);
	    	if (t.left == t.bottom.left)
	    		ll = new Point(t.left.x, t.left.y, mapcolour, "ll" + counter);
	    	else
	    		ll = new Point(t.left.x, t.left.down, mapcolour, "ll" + counter);
	    	if (t.right == t.top.right)
	    		ur = new Point(t.right.x, t.right.y, mapcolour, "ur" + counter);
	    	else
	       		ur = new Point(t.right.x, t.right.up, mapcolour, "ur"+ counter);
	    	if (t.right == t.bottom.right)
	    		lr = new Point(t.right.x, t.right.y, mapcolour, "lr"+ counter);
	    	else
	    		lr = new Point(t.right.x, t.right.down, mapcolour, "lr"+ counter);
	    	
	    	if (t.right != t.top.right && t.right != t.bottom.right)
	    		result.add(new Point(t.right.x, t.right.y, mapcolour, "middleright"+ counter));
	    	
	    	if (t.left != t.top.left && t.left != t.bottom.left)
	    		result.add(new Point(t.left.x, t.left.y, mapcolour, "middleleft"+ counter));
	    		    	
			
			if (ul.x > minX && ll.x > minX){
				upperPoints.add(ul);
				lowerPoints.add(ll);
				result.add(ul);
				result.add(ll);
			}
			if (ur.x < maxX && lr.x < maxX){
				upperPoints.add(ur);
				lowerPoints.add(lr);
				result.add(ur);
				result.add(lr);
			}
    	}	
		
		return result;
    }

    public List<Segment> getTrapezoidalSegments(){
		List<Segment> result = new LinkedList<Segment>();
		
		for (int i=0; i<upperPoints.size(); i++){		
			Segment s = new Segment(upperPoints.get(i), lowerPoints.get(i), mapcolour);		
			result.add(s);
		}
		
		return result;
    }
    
    public List<Point> getActualPoints(){
    	LinkedList<Point> result = new LinkedList<Point>();
    	for (Trapezoid t: trap){
    		result.add(t.getTop().left);
    		result.add(t.getTop().right);
    		result.add(t.getBottom().left);
    		result.add(t.getBottom().right);
    	}
    	return result; 
    }
    
    public List<Segment> getActualSegments(){
    	LinkedList<Segment> result = new LinkedList<Segment>();
    	if (trap.size()>0){
	    	Trapezoid pierwszy = trap.get(0);
	    	result.add(new Segment(pierwszy.bottom.left, pierwszy.top.left,boardercolour));
	    	result.add(new Segment(pierwszy.bottom.right, pierwszy.top.right,boardercolour));
    	}
    	for (Trapezoid t: trap){
    		result.add(t.getTop());
    		result.add(t.getBottom());
    	}
    	return result; 
    }
    
    public void saveState(){
    	List<Point> statePoints = new LinkedList<Point>();
    	List<Segment> stateSegments = new LinkedList<Segment>();
    	
    	for (Point p: getActualPoints())
    		statePoints.add(p);
    	for (Segment s: getActualSegments())
    		stateSegments.add(s);
    	for (Point p: getTrapezoidalPoints())
    		statePoints.add(p);
    	for (Segment s: getTrapezoidalSegments())
        	stateSegments.add(s);
    	for (Segment s: baseSegments)
    		stateSegments.add(s);
    	iom.saveToFile(statePoints, stateSegments);
    	upperPoints.clear();
    	lowerPoints.clear();
    	nrOfStates++;
    }
    
    public void saveStateFinal(){
    	List<Point> statePoints = new LinkedList<Point>();
    	List<Segment> stateSegments = new LinkedList<Segment>();
    	
    	for (Point p: getActualPoints())
    		statePoints.add(p);
    	for (Segment s: getActualSegments())
    		stateSegments.add(s);
    	for (Point p: getTrapezoidalPoints())
    		statePoints.add(p);
    	for (Segment s: getTrapezoidalSegments())
        	stateSegments.add(s);
    	for (Segment s: baseSegments)
    		stateSegments.add(s);
		for (Point p: getResultPoints())
			statePoints.add(p);
		for (Segment s: getResultSegments())
			stateSegments.add(s);
		lookout.colour = foundcolour;
		statePoints.add(lookout);
		
    	iom.saveToFile(statePoints, stateSegments);
    	nrOfStates++;
    }
    
    public void saveSearchState(Node n){
    	List<Point> statePoints = new LinkedList<Point>();
    	List<Segment> stateSegments = new LinkedList<Segment>();

    	for (Point p: getActualPoints())
    		statePoints.add(p);
    	for (Segment s: getActualSegments())
    		stateSegments.add(s);
    	for (Point p: getTrapezoidalPoints())
    		statePoints.add(p);
    	for (Segment s: getTrapezoidalSegments())
        	stateSegments.add(s);
    	for (Segment s: baseSegments)
    		stateSegments.add(s);
    	
    	if (n.t != null && n.t.left != null && n.t.right != null && n.t.top != null && n.t.bottom !=null){
    		trapezoid = n.t;
			for (Point p: getResultPoints())
				statePoints.add(p);
			for (Segment s: getResultSegments())
				stateSegments.add(s);
		}
		lookout.colour = foundcolour;
		statePoints.add(lookout);
		
		if (n.p != null){
			Point test1 = n.p;
			test1.colour = test;
			statePoints.add(test1);
		}
		if (n.segment != null){
			Segment test2 = n.segment;
			test2.colour = test;
			stateSegments.add(test2);
		}
	
    	iom.saveToFile(statePoints, stateSegments);
    	upperPoints.clear();
    	lowerPoints.clear();
    	nrOfStates++;
    }
}
